package graph.drawings;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.QuadCurve2D;
import java.awt.geom.QuadCurve2D.Double;

import graph.models.Edge;

public class EdgeDrawing extends AbtractDrawing {
	// private Edge edge;
	private VertexDrawing start;
	private VertexDrawing end;
	private int value;
	
	public EdgeDrawing(VertexDrawing start, VertexDrawing currentDrawing) {
		this.start = start;
		this.end = currentDrawing;
		this.key = String.format("%s>%s", start.getKey(), end.getKey());
		bound = new Bound();
		updateBoundByPosition();
	}
	

	@Override
	public void draw(Graphics2D graphics) {
		graphics.setColor(Setting.EdgeColor);
		drawArc(graphics, start.getPosition(), end.getPosition(),
				Setting.VertexSize);
		if (selected)
			drawHandles(graphics);
	}

	private void drawArc(Graphics2D graphics) {
		double x1 = start.getPosition().getX();
		double y1 = start.getPosition().getY();
		double x2 = end.getPosition().getX();
		double y2 = end.getPosition().getY();

	}

	@Override
	public void drawHandles(Graphics2D graphics) {
		double x1 = (this.start.getPosition().getX() + this.end.getPosition()
				.getX()) / 2;
		double y1 = (this.start.getPosition().getY() + this.end.getPosition()
				.getY()) / 2;
		graphics.setColor(Color.GRAY);
		drawHandle(graphics, x1, y1);
	}

	@Override
	public boolean testHit(Point point) {
		// return bound.ContainsPoint(point.x, point.y);
		return false;
	}

	public int getValue() {
		return this.value;
	}
	
	public void setValue(int value) {
		this.value = value;
	}
	
	public VertexDrawing getStartVertex() {
		return start;
	}
	
	public VertexDrawing getEndVertex() {
		return end;
	}
	
	private void updateBoundByPosition() {
		Point2D p1 = start.getPosition();
		Point2D p2 = end.getPosition();

		double x1 = Math.min(p1.getX(), p2.getX()) - 2;
		double x2 = Math.max(p1.getX(), p2.getX()) + 2;
		double y1 = Math.min(p1.getY(), p2.getY()) - 2;
		double y2 = Math.max(p1.getY(), p2.getY()) + 2;

		bound.setBound(x1, y1, x2, y2);
	}

	private void drawArc(Graphics2D graphics2D, Point2D p1, Point2D p2, double R) {

		double x1 = p1.getX();
		double y1 = p1.getY();
		double x2 = p2.getX();
		double y2 = p2.getY();

		double k = (x2 == x1) ? 0 : (y2 - y1) / (x2 - x1);
		double alpha = atanByAlpha(k);

		double length = Math
				.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));

		double x = x1;
		double y = y1 - R;
		int sign = (x2 > x1) ? 1 : -1;
		Arc2D.Double arc2D = new Arc2D.Double(x, y, length, R * 2, 0, 180,
				Arc2D.OPEN);

		AffineTransform at = new AffineTransform();
		if (sign == 1) {
			at.rotate(Math.toRadians(alpha), x1, y1);
		} else {
			at.rotate(Math.toRadians(alpha + 180), x1, y1);
		}
		// // Get the current transform
		AffineTransform saveAT = graphics2D.getTransform();
		// Perform transformation
		graphics2D.transform(at);
		// // Render
		graphics2D.draw(arc2D);
		drawArrow(graphics2D, p1, p2, R);
		// // Restore original transform
		graphics2D.setTransform(saveAT);

		if (x1 > x2) {
			Font font = Setting.VertexFont;
			graphics2D.setFont(Setting.VertexFont);
			graphics2D.drawString(String.valueOf(this.value), (float) (x1 + x2) / 2 - 10,
					(float) ((y1 + y2) / 2 + R - 5));
		}
			
	}

	private void drawArrow(Graphics2D graphics2D, Point2D p1, Point2D p2,
			double R) {
		double x1 = p1.getX();
		double y1 = p1.getY();
		double x2 = p2.getX();
		double y2 = p2.getY();
		double length = Math
				.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));

		double centerX = p1.getX() + length / 2;
		double centerY = p1.getY() - R;

		Point2D.Double arrow1 = new Point2D.Double(centerX - 7, centerY - 4);
		Point2D.Double arrow2 = new Point2D.Double(centerX - 7, centerY + 4);

		graphics2D
				.draw(new Line2D.Double(arrow1.x, arrow1.y, centerX, centerY));
		graphics2D
				.draw(new Line2D.Double(arrow2.x, arrow2.y, centerX, centerY));

		if (x2 >= x1) {
			Font font = Setting.VertexFont;
			graphics2D.setFont(Setting.VertexFont);
			graphics2D.drawString(String.valueOf(this.value), (float) centerX, (float) centerY);
		}
			

	}

	private double atanByAlpha(double value) {
		double radian = Math.atan(value);

		return Math.toDegrees(radian);
	}

}
